home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD ROM Paradise Collection 4
/
CD ROM Paradise Collection 4 1995 Nov.iso
/
program
/
recio212.zip
/
rget.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-01-29
|
23KB
|
623 lines
/*****************************************************************************
MODULE: rget.c
PURPOSE: recio input functions
COPYRIGHT: (C) 1994-1995, William Pierpoint
COMPILER: Borland C Version 3.1
OS: MSDOS Version 6.2
VERSION: 2.12
RELEASE: January 29, 1995
*****************************************************************************/
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "recio.h"
extern int _risready(REC *rp, int mode);
extern int _rmoderror(REC *rp, int mode);
extern void _rsetexitfn(REC *rp);
/* private macros */
#define RECBUFSIZ_MIN 2 /* min one character and new line */
#define FLDBUFSIZ_MIN 1 /* min one character */
#define RECBUFSIZE max(RECBUFSIZ, RECBUFSIZ_MIN)
#define FLDBUFSIZE max(FLDBUFSIZ, FLDBUFSIZ_MIN)
#define rcol(rp) ((rp)->r_colno)
#define rflags(rp) ((rp)->r_flags)
#define rfd(rp) ((rp)->r_fd)
#define rfp(rp) ((rp)->r_fp)
#define rreclen(rp) ((rp)->r_reclen)
#define rrecsiz(rp) ((rp)->r_recsiz)
#define rfldsiz(rp) ((rp)->r_fldsiz)
#define rfldch(rp) ((rp)->r_fldch)
#define rtxtch(rp) ((rp)->r_txtch)
/****************************************************************************/
static int /* return error number (0=no error) */
_rsetfldsiz( /* set field buffer size */
REC *rp, /* record pointer */
size_t fldsiz) /* field buffer size */
/****************************************************************************/
{
int errnum=0; /* error number */
char *fldp; /* pointer to new field buffer */
/* if no memory allocated to field buffer */
if (!rflds(rp)) {
/* determine minimum size of field buffer */
fldsiz = max(fldsiz, FLDBUFSIZE);
/* initially allocate memory for field buffer */
do {
fldp = (char *) calloc(fldsiz+1, sizeof(char));
if (!fldp) {
errnum = rseterr(rp, R_ENOMEM);
if (errnum) goto done;
}
} while (!fldp);
rflds(rp) = fldp;
rfldsiz(rp) = fldsiz;
_rsetexitfn(rp);
/* if field buffer needs to be larger */
} else if (fldsiz > rfldsiz(rp)) {
/* reallocate memory for field buffer */
do {
fldp = (char *) realloc(rflds(rp), fldsiz+1);
if (!fldp) {
errnum = rseterr(rp, R_ENOMEM);
if (errnum) goto done;
}
} while (!fldp);
rflds(rp) = fldp;
rfldsiz(rp) = fldsiz;
}
done:
return errnum;
}
/****************************************************************************/
static int /* return error number (0=no error) */
_rsetrecsiz( /* set record buffer size */
REC *rp, /* record pointer */
size_t recsiz) /* record buffer size */
/****************************************************************************/
{
int errnum=0; /* error number */
char *recp; /* pointer to new record buffer */
/* if no memory allocated to field buffer */
if (!rrecs(rp)) {
/* determine minimum size of record buffer */
recsiz = max(recsiz, RECBUFSIZE);
/* initially allocate memory for record buffer */
do {
recp = (char *) calloc(recsiz+1, sizeof(char));
if (!recp) {
errnum = rseterr(rp, R_ENOMEM);
if (errnum) goto done;
}
} while (!recp);
rrecs(rp) = recp;
rrecsiz(rp) = recsiz;
_rsetexitfn(rp);
/* if record buffer needs to be larger */
} else if (recsiz > rrecsiz(rp)) {
/* reallocate memory for record buffer */
do {
recp = (char *) realloc(rrecs(rp), recsiz+1);
if (!recp) {
errnum = rseterr(rp, R_ENOMEM);
if (errnum) goto done;
}
} while (!recp);
rrecs(rp) = recp;
rrecsiz(rp) = recsiz;
}
done:
return errnum;
}
/****************************************************************************/
static int /* return !0 on match */
risfldch( /* is character the field separator character? */
REC *rp, /* record pointer */
int ch) /* character to test */
/****************************************************************************/
{
int ismatch=0; /* return 0 if no match */
if (isascii(ch)) {
if (rfldch(rp) == ' ') {
ismatch = isspace(ch);
} else {
ismatch = (!(ch - rfldch(rp)));
}
}
return ismatch;
}
/****************************************************************************/
static int /* return !0 on match */
ristxtch( /* is character the text delimiter character? */
REC *rp, /* record pointer */
int ch) /* character to test */
/****************************************************************************/
{
int ismatch=0; /* return 0 if no match */
if (isascii(ch)) {
if (rtxtch(rp) == ' ') {
ismatch = isspace(ch);
} else {
ismatch = (!(ch - rtxtch(rp)));
}
}
return ismatch;
}
/****************************************************************************/
static size_t /* return length of field */
_rfldlen( /* get length of field */
REC *rp) /* record pointer */
/****************************************************************************/
{
size_t len=0; /* length of field (0=missing field) */
size_t col; /* column location */
size_t co; /* temporary column location */
int qstate=0; /* nested quoted text state (0=off; 1=on) */
/* clear quoted text char flag */
rflags(rp) &= ~_R_TXT;
/* skip past any leading whitespace */
for (col=rcol(rp); col < rreclen(rp); col++) {
if (!isspace(rrecs(rp)[col])) break;
}
/* is first non-whitespace character the txtch? */
if (ristxtch(rp, rrecs(rp)[col])) { /* yes, quoted text */
rflags(rp) |= _R_TXT; /* set quoted text char flag */
if (risfldch(rp, ' ')) { /* fldch == ' '; txtch != ' ' */
/* skip over characters that are not txtch */
for (col++; col < rreclen(rp); col++) {
/* if txtch, see if end-of-field */
if (ristxtch(rp, rrecs(rp)[col])) {
/* don't end field within any nested quoted text */
if (ristxtch(rp, '"')) {
qstate = !qstate;
if (!qstate) continue;
}
/* if whitespace follows txtch, then end-of-field */
if (isspace(rrecs(rp)[col+1])) {
/* skip to end of trailing whitespace */
for (col++; col < rreclen(rp); col++) {
if (!isspace(rrecs(rp)[col])) {
col--;
break;
}
}
break;
}
}
}
} else { /* fldch != ' '; txtch != ' ' */
/* skip over characters that are not txtch */
for (col++; col < rreclen(rp); col++) {
/* if txtch, see if end-of-field */
if (ristxtch(rp, rrecs(rp)[col])) {
/* don't end field within any nested quoted text */
if (ristxtch(rp, '"')) {
qstate = !qstate;
if (!qstate) continue;
}
/* skip any whitespace */
for (co=col+1; co < rreclen(rp); co++) {
if (!isspace(rrecs(rp)[co])) break;
}
/* if fldch, then end-of-field */
if (risfldch(rp, rrecs(rp)[co])) {
col = co;
break;
}
}
}
}
} else { /* else not quoted text */
if (risfldch(rp, ' ')) { /* fldch == ' '; txtch == ' ' */
/* skip non-whitespace */
for (; col < rreclen(rp); col++) {
if (isspace(rrecs(rp)[col])) break;
}
/* skip to end of trailing whitespace */
for (; col < rreclen(rp); col++) {
if (!isspace(rrecs(rp)[col])) {
col--;
break;
}
}
} else { /* fldch != ' '; txtch == ' ' */
/* skip over characters until fldch reached */
for (; col < rreclen(rp); col++) {
if (risfldch(rp, rrecs(rp)[col])) break;
}
}
}
/* get length of field */
if (rcol(rp) < rreclen(rp)) {
len = col - rcol(rp) + 1;
}
return len;
}
/****************************************************************************/
static int /* return error state (0=no error; EOF=error) */
_rskipfld( /* skip to the next field */
REC *rp, /* record pointer */
size_t len) /* length of field if known, 0 if unknown */
/****************************************************************************/
{
int err=0; /* error state (0=no error; EOF=past end-of-record) */
/* make sure first record is read from file */
if (!rrecno(rp) && !rgetrec(rp)) goto done;
/* if length of field is unknown */
if (!len) {
/* determine length */
len=_rfldlen(rp);
}
/* if field delimiter is whitespace */
if (risfldch(rp, ' ')) {
/* if not at end of record */
if (rcol(rp) < rreclen(rp)) {
/* move to next field */
rcol(rp) += max(len, 1);
} else {
/* cannot move beyond end of record */
err = EOF;
}
} else {
/* allow for empty field past last field delimiter */
if (rcol(rp) <= rreclen(rp)) {
/* move to next field */
rcol(rp) += max(len, 1);
} else {
/* cannot move beyond end of record */
err = EOF;
}
}
rfldno(rp)++;
done:
return err;
}
/****************************************************************************/
char * /* return pointer to field buffer (NULL=error) */
_rfldstr( /* copy field from record to field buffer */
REC *rp, /* record pointer */
size_t len) /* length of field if known; 0 if unknown */
/****************************************************************************/
{
char *fldp=NULL; /* pointer to field buffer (NULL=error) */
size_t fldlen=len; /* computed length of field */
/* make sure first record is read from file */
if (!rrecno(rp) && !rgetrec(rp)) goto done;
/* if character delimited field, compute length */
if (!fldlen) {
fldlen=_rfldlen(rp);
/* if column delimited field, avoid overflow */
} else if (rcol(rp) > rreclen(rp)) {
fldlen = 0;
}
/* ensure field buffer has sufficient memory */
if (_rsetfldsiz(rp, fldlen)) goto done;
/* copy field from record buffer to field buffer */
/* note: a missing field results in an empty string */
strncpy(rflds(rp), rrecs(rp)+rcol(rp), fldlen);
rflds(rp)[fldlen] = '\0';
/* set up for next field */
_rskipfld(rp, max(fldlen, 1));
/* if character delimited field, trim delimiters from field buffer */
if (!len) {
/* trim fldch */
scntrimends(rflds(rp), rfldch(rp), 1);
/* if whitespace field delimiter, trim whitespace */
if (risfldch(rp, ' ')) {
strims(rflds(rp));
}
/* if quoted text, trim txtch */
if (ristxtfld(rp)) {
strims(rflds(rp));
scntrims(rflds(rp), rtxtch(rp), 1);
}
}
/* assign return pointer to field buffer */
fldp = rflds(rp);
done:
return fldp;
}
/****************************************************************************/
char * /* return ptr to rec buffer (NULL=err or eof) */
rgetrec( /* read next line from file into record buffer */
REC *rp) /* record pointer */
/****************************************************************************/
{
char *retp=NULL; /* return pointer (NULL=error or eof) */
char str[FLDBUFSIZE+1]; /* temporary string */
if (_risready(rp, R_READ)) {
/* initially allocate memory for record buffer */
if (!rrecs(rp)) {
if (_rsetrecsiz(rp, RECBUFSIZE)) goto done;
}
/* for each new record */
rfldno(rp) = 0;
rcol(rp) = 0;
rrecno(rp)++;
rreclen(rp) = 0;
*rrecs(rp) = '\0';
/* if at end of file, skip reading from file */
if (reof(rp)) goto done;
/* get next line from file into record buffer */
if (!fgets(rrecs(rp), rrecsiz(rp), rfp(rp))) {
/* set end-of-file indicator if no more records */
rflags(rp) |= _R_EOF;
goto done;
}
rreclen(rp) = strlen(rrecs(rp));
/* if line longer than record buffer, extend record buffer */
while (rrecs(rp)[rreclen(rp)-1] != '\n') {
if (!fgets(str, FLDBUFSIZE+1, rfp(rp))) break;
if (_rsetrecsiz(rp, rrecsiz(rp) + FLDBUFSIZE)) goto done;
strncat(rrecs(rp), str, FLDBUFSIZE);
rreclen(rp) = strlen(rrecs(rp));
}
/* trim end of record */
sctrimends(rrecs(rp), '\n');
rreclen(rp) = strlen(rrecs(rp));
/* point retp to record buffer */
retp = rrecs(rp);
}
done:
return retp;
}
/****************************************************************************/
void /* returns nothing */
rsetrecsiz( /* set record buffer size */
REC *rp, /* record pointer */
size_t recsiz) /* record buffer size */
/****************************************************************************/
{
if (_risready(rp, R_READ)) {
_rsetrecsiz(rp, recsiz);
}
}
/****************************************************************************/
void /* returns nothing */
rsetfldsiz( /* set field buffer size */
REC *rp, /* record pointer */
size_t fldsiz) /* field buffer size */
/****************************************************************************/
{
if (_risready(rp, R_READ)) {
_rsetfldsiz(rp, fldsiz);
}
}
/****************************************************************************/
void /* returns nothing */
rsetrecstr( /* copy string to record buffer; clear errors */
REC *rp, /* record pointer */
const char *s) /* pointer to string */
/****************************************************************************/
{
size_t recsiz; /* required record buffer size */
if (risvalid(rp)) {
if (!_rmoderror(rp, R_READ)) {
if (s) {
/* ensure record buffer is large enough for string */
recsiz = strlen(s);
if (recsiz > rrecsiz(rp)) {
if (_rsetrecsiz(rp, recsiz)) goto done;
}
/* copy string to record buffer */
if (s != rrecs(rp)) strcpy(rrecs(rp), s);
/* prepare stream to read */
rclearerr(rp);
rfldno(rp) = 0;
rcol(rp) = 0;
rreclen(rp) = recsiz;
} else {
rseterr(rp, R_EINVAL);
}
}
} else {
rseterr(NULL, EINVAL);
}
done:
}
/****************************************************************************/
void /* returns nothing */
rsetfldstr( /* copy string into field buffer; clear errors */
REC *rp, /* record pointer */
const char *s) /* pointer to string */
/****************************************************************************/
{
size_t fldsiz; /* required field buffer size */
if (risvalid(rp)) {
if (!_rmoderror(rp, R_READ)) {
if (s) {
/* ensure field buffer is large enough for string */
fldsiz = strlen(s);
if (fldsiz > rfldsiz(rp)) {
if (_rsetfldsiz(rp, fldsiz)) goto done;
}
/* copy string to field buffer */
strcpy(rflds(rp), s);
/* clear away any errors */
rclearerr(rp);
} else {
rseterr(rp, R_EINVAL);
}
}
} else {
rseterr(NULL, EINVAL);
}
done:
}
/****************************************************************************/
unsigned /* return number fields skipped */
rskipnfld( /* skip over next number of fields */
REC *rp, /* record pointer */
unsigned num) /* number of fields to skip over */
/****************************************************************************/
{
unsigned count=0; /* actual number of fields skipped */
if (_risready(rp, R_READ)) {
/* count number of fields to skip */
while (count < num) {
/* but don't count past end of record */
if (_rskipfld(rp, 0)) break;
count++;
}
}
return count;
}
/****************************************************************************/
void /* returns nothing */
_rgetfldpos( /* get field position */
REC *rp, /* record pointer */
rpos_t *pos) /* pointer to field position */
/****************************************************************************/
{
if (_risready(rp, R_READ)) {
rfd(pos) = rfd(rp);
rfldno(pos) = rfldno(rp);
rcol(pos) = rcol(rp);
rrecno(pos) = rrecno(rp);
}
}
/****************************************************************************/
void /* returns nothing */
_rsetfldpos( /* set field position */
REC *rp, /* record pointer */
const rpos_t *pos) /* pointer to field position */
/****************************************************************************/
{
if (_risready(rp, R_READ)) {
if (rfd(pos)==rfd(rp) && rrecno(pos)==rrecno(rp)) {
rfldno(rp) = rfldno(pos);
rcol(rp) = rcol(pos);
} else {
rseterr(rp, R_EINVAL);
}
}
}
/****************************************************************************/
unsigned /* return number of fields in current record */
rnumfld( /* number of fields in current record */
REC *rp) /* record pointer */
/****************************************************************************/
{
unsigned num=0; /* return number of fields in current record */
rpos_t pos; /* field position */
if (_risready(rp, R_READ)) {
/* store current field information */
rgetfldpos(rp, pos);
/* get number of fields from beginning of record */
rfldno(rp) = 0;
rcol(rp) = 0;
num = rskipnfld(rp, UINT_MAX);
/* restore field information */
rsetfldpos(rp, pos);
}
return num;
}
/****************************************************************************/
unsigned long /* return unsigned long */
str2ul( /* convert string to unsigned long */
const char *nptr, /* pointer to string to convert */
char **endptr, /* pointer to conversion leftover string */
int base) /* base (radix) of number */
/****************************************************************************/
/* note: unlike strtoul, str2ul tests for a negative number */
{
unsigned long ul=0UL; /* result to return */
const char *np=nptr; /* pointer to string */
/* skip over white space */
while (isspace(*np)) np++;
/* if first non-white space is a minus sign */
if (*np == '-') {
/* position endptr at the minus sign */
if (endptr) *endptr = (char *) np;
} else {
ul = strtoul(nptr, endptr, base);
}
return ul;
}